package cn.com.headfree.file.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.gta.edu.sdk.common.dto.ResultData;
import com.gta.edu.sdk.util.IdGen;
import com.gta.edu.sdk.util.StringUtil;

import cn.com.headfree.base.common.OSSFileClient;
import cn.com.headfree.base.common.UploadResult;
import cn.com.headfree.file.entity.TCommonFile;
import cn.com.headfree.file.service.IFileService;

/**
 * Title:文件管理服务 Description: Copyright: Copyright (c) 2017 Company:
 * www.headfree.com.cn
 * 
 * @author
 * @version 1.0
 * @date 2019年7月10日 上午11:28:22
 */
@CrossOrigin("*")
@RestController
@RequestMapping(value = "/file", produces = "application/json;charset=UTF-8")
public class FileController {
	private static final Logger LOG = LogManager.getLogger(FileController.class);

	@Value("${file.save.path}")
	private String filePath; // 从配置文件中读取写入文件的路径信息

	@Autowired
	private IFileService fileService; // 文件业务处理类的引用

	@Autowired
	private OSSFileClient oSSFileClient; // OSS文件上传服务
	
	
	private static String fileExtName; // 允许通过的扩展名
	private static List<String> fileExtNameList; // 允许通过的扩展名

	
//	
//	@RequestMapping("/myJob")
//	public ResultData myJob() {
//		ResultData result = new ResultData();
//		LOG.info("我被调用了！！");
//		return result;
//	}
	
	@Value("${file.ext.name}")
	public void setFileExtName(String fileExtName) {
		FileController.fileExtName = fileExtName;
		String[] fileExtNames = fileExtName.split(",");
		fileExtNameList=Arrays.asList(fileExtNames);
	}

	/**
	 * @description 上传文件
	 * @author 冯亚
	 * @date 2019年7月11日 下午5:09:08
	 * @param file
	 * @param commonFile
	 * @return
	 * @return ResultData
	 */
	@RequestMapping("/upload")
	public ResultData upload(@RequestParam("file") MultipartFile file, TCommonFile commonFile) {
		ResultData result = new ResultData();
		if (file.isEmpty()) {
			LOG.error("上传文件为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("上传文件为空，出现错误！");
			return result;
		}
		if (StringUtil.isNullOrEmpty(commonFile.getSysCode()) || StringUtil.isNullOrEmpty(commonFile.getBusinessId())) {
			LOG.error("上传文件为空，出现错误！");
			result.setSuccess(false);
			result.setErrorMsg("上传文件为空，出现错误！");
			return result;
		}
		
		try {
			String fileName = file.getOriginalFilename();
			int index = fileName.lastIndexOf(".");
			String id = IdGen.uuid();
			String newFileName = null;
			String suffixName = null;
			if (index != -1) {
				suffixName = fileName.substring(index);
				commonFile.setExtName(suffixName);
				newFileName = id + suffixName;
			} else {
				newFileName = id;
			}
			if(newFileName==null || !fileExtNameList.contains(suffixName)) {
				LOG.error("上传文件格式错误！");
				result.setSuccess(false);
				result.setErrorMsg("上传文件格式错误，请上传.doc,.docx,.xls,.xlsx,.bmp,.jpg,.jpeg,.png,.txt,.ppt,.pptx,.pdf,.zip,.rar,.ceb,.wps,.vsd,.vsdx,.mpp,.mppx格式的文件。");
				return result;
			}
			
			commonFile.setOldFileName(fileName);
			commonFile.setFileSize(file.getSize());
			commonFile.setId(id);
			commonFile.setNewFileName(newFileName);
			commonFile.setPath(commonFile.getSysCode());
			commonFile.setUploadTime(new Date());
			//测试环境放开
			String saveFilePath = this.filePath + File.separator + commonFile.getSysCode();
			File dest = new File(saveFilePath, newFileName);
			if (!dest.getParentFile().exists()) {
				dest.getParentFile().mkdirs();
			}
			file.transferTo(dest);
			//云平台环境放开
//			int uploadResult = oSSFileClient.upload(commonFile.getSysCode() + "/" + newFileName, file.getInputStream());
			this.fileService.save(commonFile);
			result.setData(commonFile);
			//云平台环境放开
//			if (uploadResult == UploadResult.OUT_TIME.getIndex()) {
//				result.setSuccess(false);
//				result.setErrorMsg("系统繁忙，请稍后再试！");
//			}
		} catch (Exception e) {
			LOG.error("上传文件失败，系统出现异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("上传文件失败，系统出现异常！");
		}
		return result;
	}

	/**
	 * @description 根据系统编码和业务Id以及业务节点值获得该节点下所有的文件列表，如果节点为空，可以不传，获得的是该系统编码下业务ID的所有文件列表
	 * @author 冯亚
	 * @date 2019年7月11日 下午5:10:34
	 * @param sysCode
	 * @param businessId
	 * @param businessNode
	 * @return
	 * @return ResultData
	 */
	@GetMapping("/findFileList")
	public ResultData findFileList(@RequestParam(required = true) String sysCode, @RequestParam(required = true) String businessId, String businessNode) {
		ResultData result = new ResultData();
		try {
			List<TCommonFile> fileList = this.fileService.findFile(sysCode, businessId, businessNode);
			result.setData(fileList);
		} catch (Exception e) {
			LOG.error("查询文件列表出现了异常！", e);
			result.setSuccess(false);
			result.setErrorMsg("查询文件列表出现了异常！");
		}
		return result;
	}

	private String getFileName(String fileName, HttpServletRequest request) throws Exception {
		String agent = request.getHeader("User-Agent");
		if (agent.contains("Edge")) { // Edge 已测试
			fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");// 处理空格转为加号的问题
		} else if (agent.contains("Chrome")) { // google 已测试
			fileName = new String(fileName.getBytes(), "iso8859-1");
		} else if (agent.contains("Firefox")) { // Firefox 待测试
			fileName = new String(fileName.getBytes(), "iso8859-1");
		} else if (agent.contains("MSIE") || agent.contains("Trident")) { // IE11 已测试
			// 在IE8以后，微软使用了Trident来作为IE浏览器的标志，兼容老的版本
			fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");// 处理空格转为加号的问题
		} else {
			// 其余浏览器 可测试并添加
			fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");// 待测试
		}
		return fileName;
	}

	@RequestMapping("/viewFile")
	public ResultData viewFile(HttpServletResponse response, HttpServletRequest request, @RequestParam(required = true) String fileId) {
		ResultData result = new ResultData();
		InputStream is = null;
		try {
			TCommonFile commonFile = this.fileService.getFile(fileId);
//			File path = new File("E:\\workspace-aliyun\\common-module-aliyun\\comm-work-flow-server\\target\\classes\\static\\commons\\video/bkaovAYt-480.jpg");
			File path = new File(this.filePath + "/" + commonFile.getPath());
			if (!path.exists()) {
				path.mkdirs();
			}
			File file = new File(path, commonFile.getNewFileName());

			int downResult = oSSFileClient.down(commonFile.getSysCode() + "/" + commonFile.getNewFileName(), file);
			if (downResult == UploadResult.OUT_TIME.getIndex()) {
				response.sendRedirect("/comm-file-server/error.html");
				return null;
			}
			if (!file.exists()) {
				return null;
			}
			is = new FileInputStream(file);
			byte[] bytes = new byte[(int) file.length()];
			is.read(bytes);
			result.setData(Base64.getEncoder().encodeToString(bytes));
		} catch (Exception e) {
			result.setSuccess(false);
			result.setErrorMsg("文件预览出现异常!");
			LOG.error("文件预览出现异常！", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	@RequestMapping("/download")
	public void downloadFile(HttpServletResponse response, HttpServletRequest request, @RequestParam(required = true) String fileId) {
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		try {
			TCommonFile commonFile = this.fileService.getFile(fileId);
			File path = new File(this.filePath + "/" + commonFile.getPath());
			if (!path.exists()) {
				path.mkdirs();
			}
			File file = new File(path, commonFile.getNewFileName());

			int downResult = oSSFileClient.down(commonFile.getSysCode() + "/" + commonFile.getNewFileName(), file);
			if (downResult == UploadResult.OUT_TIME.getIndex()) {
				response.sendRedirect("/comm-file-server/error.html");
				return;
			}
			if (!file.exists()) {
				return;
			}
			String fileName = commonFile.getOldFileName();
			response.setHeader("content-type", "application/octet-stream");
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment;filename=" + this.getFileName(fileName, request));
			// 实现文件下载
			byte[] buffer = new byte[1024];
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			OutputStream os = response.getOutputStream();
			int i = bis.read(buffer);
			while (i != -1) {
				os.write(buffer, 0, i);
				i = bis.read(buffer);
			}
		} catch (Exception e) {
			LOG.error("文件下载出现异常！", e);
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * @description 删除文件
	 * @author 冯亚
	 * @date 2019年7月12日 上午10:58:49
	 * @param fileId
	 * @return
	 * @return ResultData
	 */
	@RequestMapping("/deleteFile")
	public ResultData deleteFile(@RequestParam(required = true) String fileId) {
		ResultData result = new ResultData();
		
		if (StringUtil.isNullOrEmpty(fileId)) {
			LOG.error("删除文件出现了异常！原因：文件ID为空！");
			result.setSuccess(false);
			result.setErrorMsg("删除文件出现了异常！原因：文件ID为空！");
		} else {
			try {
				TCommonFile commonFile = this.fileService.getFile(fileId);
				int deleteResult = oSSFileClient.delete(commonFile.getSysCode() + "/" + commonFile.getId() + commonFile.getExtName());
				if (deleteResult == UploadResult.OUT_TIME.getIndex()) {
					result.setSuccess(false);
					result.setErrorMsg("系统繁忙，请稍后再试！");
				}
				this.fileService.deleteFile(fileId);
			} catch (Exception e) {
				LOG.error("删除文件出现了异常！", e);
				result.setSuccess(false);
				result.setErrorMsg("删除文件出现了异常！");
			}
		}
		
		return result;
	}

}
